/*
 * @Author: Wangjun
 * @Date: 2021-06-08 19:24:15
 * @LastEditTime: 2022-10-27 13:44:30
 * @LastEditors: Wangjun
 * @Description:all
 * @FilePath: \query\global_func.go
 * hnxr
 */

package query

import (
	"gitee.com/haodreams/libs/easy"
)

// ===================过滤函数===================
func GT(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.GT(key, value, true)
}
func OrGT(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.GT(key, value, false)
}
func GE(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.GE(key, value, true)
}
func OrGE(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.GE(key, value, false)
}

func LT(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.LT(key, value, true)
}
func OrLT(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.LT(key, value, false)
}

func LE(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.LE(key, value, true)
}
func OrLE(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.LE(key, value, false)
}

func NE(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.NE(key, value, true)
}
func OrNE(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.NE(key, value, false)
}

func EQ(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.EQ(key, value, true)
}

func IN(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()

	n := len(params)
	if params[1].Number == nil {
		svalues := make([]string, n-1)
		for i := 1; i < n; i++ {
			svalues[i-1] = *params[i].String
		}
		return q.IN(key, svalues, true)
	}
	fvalues := make([]float64, n-1)
	for i := 1; i < n; i++ {
		fvalues[i-1] = *params[i].Number
	}

	return q.IN(key, fvalues, true)
}

func OrIN(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()

	n := len(params)
	if params[0].Number == nil {
		svalues := make([]string, n-1)
		for i := 1; i < n; i++ {
			svalues[i-1] = *params[i].String
		}
		return q.IN(key, svalues, true)
	}
	fvalues := make([]float64, n-1)
	for i := 1; i < n; i++ {
		fvalues[i-1] = *params[i].Number
	}

	return q.IN(key, fvalues, false)
}

func OrEQ(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.EQ(key, value, false)
}

func Like(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.Like(key, value, true)
}

// 或
func OrLike(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.Like(key, value, false)
}

func Match(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.Match(key, value, true)
}

// 或
func OrMatch(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value := params[1].GetValue()
	return q.Match(key, value, false)
}

// ===================统计函数===================
// 最大值
func Max(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value, err := q.Max(key)
	q.result = value
	return q, err
}

func Min(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value, err := q.Min(key)
	q.result = value
	return q, err
}

func Avg(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value, err := q.Avg(key)
	q.result = value
	return q, err
}

func Sum(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value, err := q.Sum(key)
	q.result = value
	return q, err
}

func Count(q *Table, params []*Param) (*Table, error) {
	key := params[0].Key()
	value, err := q.Count(key)
	q.result = value
	return q, err
}

// 乘法
func Mult(q *Table, params []*Param) (*Table, error) {
	value := params[0].Float64()
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}
	result *= value
	q.result = result
	return q, err
}

// 除法
func Divi(q *Table, params []*Param) (*Table, error) {
	value := params[0].Float64()
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}
	result /= value
	q.result = result
	return q, err
}

// 加法
func Add(q *Table, params []*Param) (*Table, error) {
	value := params[0].Float64()
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}
	result += value
	q.result = result
	return q, err
}

// 减法
func Sub(q *Table, params []*Param) (*Table, error) {
	value := params[0].Float64()
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}
	result -= value
	q.result = result
	return q, err
}

// ColSum 变量相加
func ColSum(q *Table, params []*Param) (*Table, error) {
	total := 0.0
	for _, param := range params {
		if param.String != nil {
			val, err := q.Column(*param.String)
			if err != nil {
				q.result = 0
				return q, err
			}
			total += val
		} else {
			total += *param.Number
		}
	}
	q.result = total
	return q, nil
}

// ColSum 列求平均
func ColAvg(q *Table, params []*Param) (*Table, error) {
	total := 0.0
	count := 0
	for _, param := range params {
		if param.String != nil {
			val, err := q.Column(*param.String)
			if err != nil {
				q.result = 0
				return q, err
			}
			total += val
		} else {
			total += *param.Number
		}
		count++
	}
	if count > 0 {
		q.result = total / float64(count)
	}
	q.result = 0
	return q, nil
}

// ColAdd 列加法
func ColAdd(q *Table, params []*Param) (*Table, error) {
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}
	for _, param := range params {
		if param.String != nil {
			val, err := q.Column(*param.String)
			if err != nil {
				q.result = 0
				return q, err
			}
			result += val
		} else {
			result += *param.Number
		}
	}
	q.result = result
	return q, nil
}

// ColAdd 列减法
func ColSub(q *Table, params []*Param) (*Table, error) {
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}
	for _, param := range params {
		if param.String != nil {
			val, err := q.Column(*param.String)
			if err != nil {
				q.result = 0
				return q, err
			}
			result -= val
		} else {
			result -= *param.Number
		}
	}
	q.result = result
	return q, nil
}

// ColAdd 列乘法
func ColMult(q *Table, params []*Param) (*Table, error) {
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}
	for _, param := range params {
		if param.String != nil {
			val, err := q.Column(*param.String)
			if err != nil {
				q.result = 0
				return q, err
			}
			result *= val
		} else {
			result *= *param.Number
		}
	}
	q.result = result
	return q, nil
}

// colCount 统计符合条件的列数
func colCount(q *Table, params []*Param, f func(a, b float64) bool) (*Table, error) {
	count := 0
	value := params[0].Float64()
	var err error
	for i, param := range params {
		if i == 0 {
			continue
		}
		val := float64(0)
		if param.String != nil {
			val, err = q.Column(*param.String)
			if err != nil {
				q.result = 0
				return q, err
			}
		} else {
			val = *param.Number
		}
		if f(val, value) {
			count++
		}
	}
	q.result = float64(count)
	return q, err
}

// ColGtCount 统计列符合条件的个数
func ColGtCount(q *Table, params []*Param) (*Table, error) {
	gt := func(a, b float64) bool {
		return a > b
	}
	return colCount(q, params, gt)
}

// ColEqCount  等于判断
func ColEqCount(q *Table, params []*Param) (*Table, error) {
	eq := func(a, b float64) bool {
		return easy.FloatEqual(a, b)
	}
	return colCount(q, params, eq)
}

// ColLtCount  小于判断
func ColLtCount(q *Table, params []*Param) (*Table, error) {
	lt := func(a, b float64) bool {
		return a < b
	}
	return colCount(q, params, lt)
}

// ifFunc 判断条件
func ifFunc(q *Table, params []*Param, f func(a, b float64) bool) (*Table, error) {
	value := params[0].Float64()
	var a interface{}
	var b interface{}
	param := params[1]
	if param.Number != nil {
		a = *param.Number
	} else {
		val, err := q.Column(param.Key())
		if err != nil {
			return q, err
		}
		a = val
	}
	param = params[2]
	if param.Number != nil {
		b = *param.Number
	} else {
		val, err := q.Column(param.Key())
		if err != nil {
			return q, err
		}
		b = val
	}
	result, err := easy.GetFloat64(q.result)
	if err != nil {
		return q, err
	}

	if f(result, value) {
		q.result = a
	} else {
		q.result = b
	}
	return q, nil
}

// IfGT if 大于判断 this>x?a:b
func IfGT(q *Table, params []*Param) (*Table, error) {
	gt := func(a, b float64) bool {
		return a > b
	}
	return ifFunc(q, params, gt)
}

// IfGT if 等于判断 this>x?a:b
func IfEQ(q *Table, params []*Param) (*Table, error) {
	eq := func(a, b float64) bool {
		return easy.FloatEqual(a, b)
	}
	return ifFunc(q, params, eq)
}

// IfGT if 小于判断 this>x?a:b
func IfLT(q *Table, params []*Param) (*Table, error) {
	lt := func(a, b float64) bool {
		return a < b
	}
	return ifFunc(q, params, lt)
}
